package com.lt.lumentracks.service.Impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lt.lumentracks.constant.CommentConstant;
import com.lt.lumentracks.constant.RedisConstant;
import com.lt.lumentracks.context.BaseContext;
import com.lt.lumentracks.entity.po.Comment;
import com.lt.lumentracks.entity.po.Post;
import com.lt.lumentracks.entity.po.User;
import com.lt.lumentracks.entity.vo.comment.CommentVO_ReplyToMe;
import com.lt.lumentracks.entity.vo.comment.CommentVO_liked;
import com.lt.lumentracks.entity.vo.comment.CommentVO_post;
import com.lt.lumentracks.entity.vo.common.PageVO;
import com.lt.lumentracks.entity.vo.common.Result;
import com.lt.lumentracks.entity.vo.user.UserVO_baseShow;
import com.lt.lumentracks.mapper.CommentMapper;
import com.lt.lumentracks.service.ICommentService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lt.lumentracks.service.IPostService;
import com.lt.lumentracks.service.IUserService;
import com.lt.lumentracks.utils.CommonUtils;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.StringRedisConnection;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 评论表 服务实现类
 * </p>
 *
 * @author swl
 * @since 2025-08-18
 */
@Slf4j
@Service
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> implements ICommentService {

    @Autowired
    private CommentMapper commentMapper;
    @Autowired
    private IUserService iUserService;
    @Autowired
    private IPostService iPostService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;


    // 增
    @Transactional
    @Override
    public Result addComment(Comment comment) {
        if(comment.getReplyId() != null){
            if(comment.getLevel() < 2){
                log.error("参数错误，回复评论的层级(level)必须大于1，用户ID：{}", comment.getUserId());
                return Result.error("参数错误"); // 只有评论层级为2时才能“回复”评论
            }
        }
        if(comment.getParentId() == 0){
            if(comment.getLevel() != 1){
                log.error("用户评论参数错误，顶层评论的层级(level)必须为1，用户ID：{}", comment.getUserId());
                return Result.error("参数错误");
            }
        }
        comment.setCreateTime(LocalDateTime.now());
        // 1.保存
        this.save(comment);

        // 2.更新该帖子的评论数量
        UpdateWrapper<Post> uw_p = new UpdateWrapper<>();
        uw_p.eq("id", comment.getPostId());
        uw_p.setSql("comments_count = comments_count + 1");
        iPostService.update(uw_p);

        // 3.设置父评论的回复数量
        if(comment.getParentId() > 0){
            updateRepliesCountById(comment.getParentId(), true);
        }

        // 4.返回展示数据
        Comment c_return = this.getById(comment.getId());
        CommentVO_post vo = new CommentVO_post();
        BeanUtils.copyProperties(c_return, vo);
        fillUser(vo, iUserService.getById(comment.getUserId()));
        vo.setChildrenComments(null);

        return Result.success(vo);
    }


    // 删
    @Transactional
    @Override
    public void removeCommentById(Integer id) {
        // 1.获取该评论
        Comment c = this.getById(id);

        // 2.更新父评论的回复数量
        updateRepliesCountById(c.getParentId(), false);

        // 3.更新该帖子的评论数量
        UpdateWrapper<Post> uw_p = new UpdateWrapper<>();
        uw_p.eq("id", c.getPostId());
        uw_p.setSql("comments_count = comments_count - 1");
        iPostService.update(uw_p);

        // 3.如果是顶级评论，则删除该评论下的所有子评论
        List<Comment> children = new ArrayList<>();
        if(c.getParentId() == 0 && c.getRepliesCount() > 0){
            children = lambdaQuery()
                    .eq(Comment::getPostId, c.getPostId())
                    .eq(Comment::getParentId, id)
                    .list();
        }

        // 4.删除评论
        List<Comment> needToDelList = new ArrayList<>();
        needToDelList.add(c);
        needToDelList.addAll(children);
        this.removeByIds(needToDelList); // 将评论及其子评论一起删除
    }


    // 改
    /** 更新回复数
     * @param comment   评论实体类
     * @param addOrMinus  true 为添加，false 为减
     */
    @Override
    public void updateRepliesCount(Comment comment, Boolean addOrMinus) {
        if(comment == null){
            return;
        }
        if(addOrMinus == null){
            log.error("参数错误，addOrMinus 不能为空");
            return;
        }
        if(comment.getParentId() != 0 && comment.getLevel() != 1){
            log.error("参数错误，非顶级评论无法设置回复数量");
            return;
        }
        LambdaUpdateWrapper<Comment> luw = new LambdaUpdateWrapper<>();
        if(addOrMinus){
            luw.setSql("replies_count = replies_count + 1");
        }else {
            luw.setSql("replies_count = replies_count - 1");
        }
        luw.eq(Comment::getId, comment.getId());
        this.update(null, luw);
    }


    // 批量更新点赞数
    @Override
    @Transactional
    public void updateLikedNumber(int batchSize) {
        // 1.读取并移除 Redis 中缓存的点赞总数
        String key = RedisConstant.COMMENT_LIKE_COUNT_KEY;
        Set<ZSetOperations.TypedTuple<String>> typedTuples = stringRedisTemplate.opsForZSet().popMin(key, batchSize); //使用 popMin 方法，从分数最小的开始弹出

        // 2.数据转换
        List<Comment> list = new ArrayList<>(typedTuples.size());
        for (ZSetOperations.TypedTuple<String> tuple : typedTuples) {
            String cid = tuple.getValue();
            Double likedNum = tuple.getScore();
            if(cid == null || likedNum == null){
                continue;
            }
            Comment c = new Comment();
            c.setId(Long.parseLong(cid));
            c.setLikesCount(likedNum.intValue());
            list.add(c);
        }

        // 3.更新 mysql 中的数据
        updateBatchById(list);
    }


    // 根据id更新某评论的回复数
    @Override
    public void updateRepliesCountById(Long cid, @NonNull Boolean addOrMinus) {
        if(cid == null || cid == 0){ // 代表没有父评论，这是顶级评论
            return;
        }
        LambdaUpdateWrapper<Comment> luw = new LambdaUpdateWrapper<>();
        if(addOrMinus){
            luw.setSql("replies_count = replies_count + 1");
        }else {
            luw.setSql("replies_count = replies_count - 1");
        }
        luw.eq(Comment::getId, cid);
        this.update(null, luw);
    }


    // 查
    // 根据文章id分页查询评论
    @Override
    public PageVO<CommentVO_post> getByPostId(Integer postId, String sortRule, long current, long size) {

        // 1.从数据库获取数据
        LambdaQueryWrapper<Comment> lqw_c = new LambdaQueryWrapper<>();
        lqw_c.eq(Comment::getPostId, postId)  // 查询指定帖子的评论
                .eq(Comment::getParentId, 0); // 只查询顶级评论
        // 排序规则
        if (CommentConstant.SORT_LATEST.equals(sortRule)) {
            lqw_c.orderByDesc(Comment::getCreateTime);
        } else {
            lqw_c.orderByDesc(Comment::getLikesCount);
            lqw_c.orderByAsc(Comment::getCreateTime); // 点赞相同时，创建时间越早的越靠前
        }
        Page<Comment> pageRes_mp = page(new Page<>(current, size), lqw_c);


        List<Comment> comment_topList = pageRes_mp.getRecords();
        if (comment_topList.isEmpty()) {
            return new PageVO<>(pageRes_mp.getTotal(), pageRes_mp.getPages(), Collections.emptyList());
        }


        // 2. 一次性把需要用到的用户查出来，避免 N+1
        Set<Integer> userIds = new HashSet<>();
        // 2.1.添加顶级评论中的用户id到集合中
        comment_topList.forEach(c -> userIds.add(c.getUserId()));

        List<Long> c_topIdList = comment_topList.stream().map(Comment::getId).toList();
        List<Comment> allChildren = commentMapper.selectChildrenTopN(postId, c_topIdList, 5); // 查询子评论（仅往后一层的）
        // 2.2.添加子评论中的用户id到集合中
        allChildren.forEach(c -> userIds.add(c.getUserId())); // 如果整篇文章，一个子评论都没有，全是顶级评论，这里不会出错，因为 allChildren 会被赋值为空集合，而不是null

        // 2.3. userIds收集完毕，开始创建用户map映射
        Map<Integer, User> userMap = iUserService.lambdaQuery()
                .in(User::getId, userIds)
                .select(User::getId, User::getUsername, User::getAvatarUrl)
                .list()
                .stream()
                .collect(Collectors.toMap(User::getId, Function.identity()));


        // 3. 组装 VO
        List<CommentVO_post> records = comment_topList.stream().map(parent -> {
            CommentVO_post cvo_parent = new CommentVO_post();
            BeanUtils.copyProperties(parent, cvo_parent); // 3.1.拷贝属性
            fillUser(cvo_parent, userMap.get(parent.getUserId())); // 3.2.组装用户信息

            // 3.3. 组装子评论（这里简单取前 N 条，也可以再做分页）
            List<CommentVO_post> childrenVo = allChildren.stream()
                    .filter(c -> c.getParentId().equals(parent.getId())) // 筛选出当前顶级评论的子评论
                    .limit(5)  // 限制查询数量（如需查询更多，请在控制层调用其他接口查询）
                    .map(child -> {
                        CommentVO_post cvo_children = new CommentVO_post();

                        BeanUtils.copyProperties(child, cvo_children);
                        fillUser(cvo_children, userMap.get(child.getUserId())); // 组装用户信息，切记这里要使用 child 的 userId
                        cvo_children.setChildrenComments(null); // 不要再往下组装子评论了

                        return cvo_children;
                    }).toList();
            cvo_parent.setChildrenComments(childrenVo);

            return cvo_parent;
        }).toList();

        PageVO<CommentVO_post> vo = new PageVO<>();
        vo.setTotal(lambdaQuery().eq(Comment::getPostId, postId).count()); // 这里设置总数，应为该帖子下所有的评论数，如果使用pageRes_mp.getTotal()的话就是顶级评论的数量了
        vo.setPages(pageRes_mp.getPages());
        vo.setList(records);
        return vo;
    }


    // 查询某帖子下的评论的子评论
    @Override
    public List<CommentVO_post> getReplies(Integer postId, Long cid, long current, long size) {
        Page<Comment> pageRes_mp = lambdaQuery()
                .eq(Comment::getPostId, postId)
                .eq(Comment::getParentId, cid)
                .orderByAsc(Comment::getCreateTime)
                .page(new Page<>(current, size));

        List<Comment> list_original = pageRes_mp.getRecords();
        List<CommentVO_post> list_vo;

        if(list_original.isEmpty()){
            return Collections.emptyList();
        }else {
            // 获取所有的用户id，根据用户id查询用户名(避免N+1问题)
            Set<Integer> userIds = list_original.stream()
                    .map(Comment::getUserId)
                    .collect(Collectors.toSet());
            Map<Integer, User> userMap = iUserService.lambdaQuery()
                    .in(User::getId, userIds)
                    .select(User::getId, User::getUsername, User::getAvatarUrl)
                    .list()
                    .stream()
                    .collect(Collectors.toMap(User::getId, Function.identity()));

            list_vo = list_original.stream().map(c -> {
                CommentVO_post cvo = new CommentVO_post();

                BeanUtils.copyProperties(c, cvo);
                fillUser(cvo, userMap.get(c.getUserId()));
                cvo.setChildrenComments(null);

                return cvo;
            }).toList();
        }

        return list_vo;
    }

    // 查询回复了我的评论
    @Override
    public Result<PageVO<CommentVO_ReplyToMe>> getForMyRelies(long current, long size) {
        Integer userId = BaseContext.getCurrentId();

        // 1.查询【回复我的】评论（别人发的）
        Page<Comment> pageParam = new Page<>(current, size);
        Page<Comment> comment_ReplyToMe_page = commentMapper.selectRepliesForMe(pageParam, userId);
        if(comment_ReplyToMe_page.getTotal() == 0){
            return Result.success("暂无回复", PageVO.empty(comment_ReplyToMe_page));
        }
        List<Comment> comment_ReplyToMe_List = comment_ReplyToMe_page.getRecords();
        if(comment_ReplyToMe_List.isEmpty()){
            return Result.success("没有更多记录", PageVO.empty(comment_ReplyToMe_page)); // 一般是超出页码范围
        }


        // 2.根据上一步的到的评论id，查询【我】的评论（我发的）
        // 提取出我发的评论的id
        List<Long> commentIds_sendByMe = comment_ReplyToMe_List.stream()
                .map(c -> c.getReplyId() == null ? c.getParentId() : c.getReplyId()) // 如果replyId为null，则parentId是我的评论；如果replyId不为null，则replyId是我的评论
                .toList();

        // 查询【我】的评论
        List<Comment> myCommentList = lambdaQuery().in(Comment::getId, commentIds_sendByMe).list();


        // 3.封装数据 Comment -> CommentVO_ReplyToMe
        List<CommentVO_ReplyToMe> list_vo = wrapC_2_CRTM(comment_ReplyToMe_List, myCommentList, userId);

        // 4.返回数据
        PageVO<CommentVO_ReplyToMe> vo = new PageVO<>();
        vo.setTotal(comment_ReplyToMe_page.getTotal());
        vo.setPages(comment_ReplyToMe_page.getPages());
        vo.setList(list_vo);
        return Result.success(vo);
    }




    /** 用户点赞评论
     * @param cid 评论的id
     * @param userId_liked 被点赞的用户的id
     * @param addOrDel true-点赞，false-取消点赞
     */
    @Override
    public void addLikeRecord(Long cid, Integer userId_liked, Boolean addOrDel) {
        // 1.基于前端参数，判断是执行点赞还是取消点赞
        boolean success = addOrDel ? like(cid, userId_liked) : cancelLike(cid, userId_liked);
        if(!success){
            return; // 添加记录失败（已经点赞过了），或者删除记录失败（没有点赞记录）
        }

        String key_cLike = RedisConstant.USER_LIKE_POST_COMMENT_KEY_PREFIX + cid;
        String key_cLikeCount = RedisConstant.COMMENT_LIKE_COUNT_KEY;

        // 2.缓存该评论的点赞总数到Redis
        Long size = stringRedisTemplate.opsForSet().size(key_cLike); // 统计（该评论的）点赞总数
        if(size != null){
            stringRedisTemplate.opsForZSet().add(key_cLikeCount, cid.toString(), size); // 原本有的话就覆盖
        }

    }

    /** 判断用户是否点赞了某些评论，找到点赞过的，把ids返回
     * @param cIds 评论的id集合
     * @return 用户点赞过的评论的id集合
     */
    @Override
    public Result<Set<Long>> isLiked(List<Long> cIds) {
        // 1.获取当前登录用户id
        Integer userId = BaseContext.getCurrentId();

        // 2.查询点赞状态
        // 要使用管道执行批量查询，一起返回结果。如果一条一条地查询并返回结果，网络往返耗时太长了。
        List<Object> objectList = stringRedisTemplate.executePipelined((RedisCallback<Object>) connection -> {
            StringRedisConnection src = (StringRedisConnection) connection; // 要用这个方法给的 connection 执行命令才有批量的效果，不过用之前记得要强转成要用的类型
            for (Long cid : cIds) {
                String key = RedisConstant.USER_LIKE_POST_COMMENT_KEY_PREFIX + cid;
                src.sIsMember(key, userId.toString()); // 依次执行 IsMember 命令，最终返回 List<Object> 类型的结果，其顺序和传入的 cIds 是一一对应的
            }
            return null;
        });

        // 3.返回结果
        Set<Long> set = new HashSet<>();
        for (int i = 0; i < objectList.size(); i++) {
            Boolean result = (Boolean) objectList.get(i); // 这里直接强转为 Boolean 就行，上面执行 IsMember 命令得到的结果肯定为 Boolean 类型
            if (result) {
                set.add(cIds.get(i));
            }
        }
        return Result.success(set);
    }


    // 查询用户最近被点赞的评论
    @Override
    public Result<PageVO<CommentVO_liked>> getMyRecentLikedComments(long current, long size) {
        // 1.获取用户id
        Integer userId = BaseContext.getCurrentId();

        // 2.查询原始数据
        // 2.1.从Redis中获取数据
        // 2.1.1.评论的id集合
        String key_c = RedisConstant.USER_COMMENT_LIKED_KEY_PREFIX + userId;
        Set<ZSetOperations.TypedTuple<String>> typedTuples = stringRedisTemplate.opsForZSet()
                .reverseRangeByScoreWithScores(
                    key_c,
                    0, // 分数的最小值
                    System.currentTimeMillis(), // 分数的最大值
                    (current - 1) * size, // 偏移量
                    (int) size // 每页大小
                );
        if (typedTuples == null || typedTuples.isEmpty()) {
            return Result.success(PageVO.empty(new Page<>()));
        }
        List<Long> cIdList = new ArrayList<>();
        Map<Long, Double> timeMap = new HashMap<>();
        for (ZSetOperations.TypedTuple<String> tuple : typedTuples) {
            String cid = tuple.getValue();
            Double likedTime = tuple.getScore();
            if(cid == null || likedTime == null){
                continue;
            }
            cIdList.add(Long.valueOf(cid)); // 评论的id集合
            timeMap.put(Long.valueOf(cid), likedTime); // 评论id-评论的点赞时间
        }

        // 2.1.2.点赞评论的用户id
        Map<Long, List<Integer>> cu_map = new HashMap<>(); // 映射 -- key:评论的id,  value:对应的点赞用户的id集合
        List<Integer> uIdList = new ArrayList<>(); // 收集所有点赞评论的用户id集合
        for(Long cId : cIdList){
            String key_u = CommonUtils.formatWithStringFormat(RedisConstant.USER_COMMENT_LIKED_AUX_KEY_PREFIX, userId, cId);
            Set<String> uIdSet = stringRedisTemplate.opsForZSet().reverseRangeByScore(key_u, 0, System.currentTimeMillis(), 0, (int) size);
            if (uIdSet == null || uIdSet.isEmpty()) {
                continue;
            }
            List<Integer> uIds = new ArrayList<>(uIdSet.size());
            for (String uId : uIdSet) {
                uIds.add(Integer.valueOf(uId));
            }
            uIdList.addAll(uIds);
            cu_map.put(cId, uIds);
        }

        // 2.2.从mysql中获数据
        // 2.2.1.评论信息
        Page<Comment> commentPage_mp = lambdaQuery()
                .in(Comment::getId, cIdList)
                .orderByDesc(Comment::getCreateTime)
                .page(new Page<>(current, size));
        List<Comment> cList = commentPage_mp.getRecords();
        if (CollUtil.isEmpty(cList)) {
            return Result.success(PageVO.empty(new Page<>(current, size)));
        }
        Map<Long, Comment> cMap = cList.stream().collect(Collectors.toMap(Comment::getId, Function.identity())); // 保持 Redis 顺序，用 Map 做索引

        // 2.2.2.用户信息
        List<User> uList = new ArrayList<>();
        if(!CollUtil.isEmpty(uIdList)){
            uList = iUserService.lambdaQuery()
                    .in(User::getId, uIdList)
                    .select(User::getId, User::getUsername, User::getAvatarUrl)
                    .list();
        }
        Map<Integer, User> uMap = CollUtil.isNotEmpty(uList)
                ? uList.stream().collect(Collectors.toMap(User::getId, Function.identity()))
                : new HashMap<>();

        // 3.封装数据
        List<CommentVO_liked> voList = cIdList.stream() // 使用 cIdList 遍历，保持顺序与 Redis 一致
                .map(cMap::get) // 拿到评论
                .filter(Objects::nonNull) // 可能 Redis 里残留脏数据
                .map(c -> {
                    CommentVO_liked vo_cl = new CommentVO_liked();
                    BeanUtils.copyProperties(c, vo_cl);

                    // 把Double类型的时间戳转成LocalDateTime
                    LocalDateTime likeTime = LocalDateTime.ofInstant(
                            Instant.ofEpochMilli(timeMap.get(c.getId()).longValue()),
                            ZoneId.of("Asia/Shanghai") // 中国时区
                    );
                    vo_cl.setLikeTime(likeTime);
                    List<Integer> likedUserId = cu_map.get(c.getId()); // 根据评论id，拿到【点赞该评论的用户id】集合
                    if(CollUtil.isNotEmpty(likedUserId)){
                        List<User> uList_temp = new ArrayList<>();
                        for(Integer uId : likedUserId){
                            uList_temp.add(uMap.get(uId));
                        }
                        fillUser_likeMyComment(vo_cl, uList_temp);
                    }else {
                        fillUser_likeMyComment(vo_cl, List.of());
                    }

                    return vo_cl;
                }).toList();

        // 4.返回数据
        PageVO<CommentVO_liked> vo = new PageVO<>();
        vo.setTotal(commentPage_mp.getTotal());
        vo.setPages(commentPage_mp.getPages());
        vo.setList(voList);
        return Result.success(vo);
    }


    // 填充用户信息
    private void fillUser(CommentVO_post vo, User user) {
        if (user == null) {
            vo.setUsername("用户已注销");
            vo.setUserAvatarUrl(null);
        } else {
            vo.setUsername(user.getUsername());
            vo.setUserAvatarUrl(user.getAvatarUrl());
        }
    }

    private void fillUser_ReplyToMe(CommentVO_ReplyToMe vo, User user) {
        if (user == null) {
            vo.setUsername("用户已注销");
            vo.setUserAvatarUrl(null);
        } else {
            vo.setUsername(user.getUsername());
            vo.setUserAvatarUrl(user.getAvatarUrl());
        }
    }

    private void fillUser_likeMyComment(CommentVO_liked vo, List<User> userList) {
        List<UserVO_baseShow> vo_user = new ArrayList<>();
        if(CollUtil.isEmpty(userList)){
            vo.setLikedUsers(List.of());
        }else {
            for(User user : userList){
                UserVO_baseShow u = new UserVO_baseShow();
                if (user == null) {
                    u.setId(-1);
                    u.setUsername("用户已注销");
                    u.setAvatarUrl(null);
                } else {
                    u.setId(user.getId());
                    u.setUsername(user.getUsername());
                    u.setAvatarUrl(user.getAvatarUrl());
                }
                vo_user.add(u);
            }
            vo.setLikedUsers(vo_user);
        }
    }


    // 封装数据 Comment -> CommentVO_ReplyToMe
    private List<CommentVO_ReplyToMe> wrapC_2_CRTM(List<Comment> comment_replyMe,
                                                   List<Comment> myCommentList,
                                                   Integer userId) {
        // 1.收集信息，方便查询
        // 1.1.收集用户id集合
        Set<Integer> userIds = comment_replyMe.stream().map(Comment::getUserId).collect(Collectors.toSet());

        // 1.2.收集我的评论内容
        Map<Long, String> myCommentContentMap = myCommentList.stream().collect(Collectors.toMap(Comment::getId, Comment::getContent));


        // 2.批量查询信息
        // 2.1.根据用户id集合批量查询用户信息
        Map<Integer, User> userMap = iUserService.lambdaQuery()
                .in(User::getId, userIds)
                .select(User::getId, User::getUsername, User::getAvatarUrl)
                .list()
                .stream()
                .collect(Collectors.toMap(User::getId, Function.identity()));

        // 3.组装数据并返回
        return comment_replyMe.stream().map(c -> {
            CommentVO_ReplyToMe cvo = new CommentVO_ReplyToMe();

            BeanUtils.copyProperties(c, cvo); // 1.拷贝基本信息
            fillUser_ReplyToMe(cvo, userMap.get(c.getUserId())); // 2.填充用户信息

            // 3.填充我的评论内容
            if(c.getReplyId() != null && Objects.equals(c.getReplyUserId(), userId)){
                cvo.setMyContent(myCommentContentMap.get(c.getReplyId())); // 我的评论是次级评论，他在精确回答我，所以此时我的评论的id是ReplyId
            }
            else {
                cvo.setMyContent(myCommentContentMap.get(c.getParentId())); // 我的评论是顶级评论，他可能是在回答他人在我评论下的发言，也可能单纯在我的评论下发言，所以此时我的评论id是ParentId
            }
            return cvo;
        }).toList();
    }

    // 用户点赞评论
    private boolean like(Long cid, Integer userId_liked) {
        // 1.获取当前用户id
        Integer userId = BaseContext.getCurrentId();

        // 2.获取key
        String key_postCLiked = RedisConstant.USER_LIKE_POST_COMMENT_KEY_PREFIX + cid; // 某条评论被哪些用户点赞，查询主体：按评论查询
        String key_userCLiked = RedisConstant.USER_COMMENT_LIKED_KEY_PREFIX + userId_liked;
        String key_userCLikedAux = CommonUtils.formatWithStringFormat(RedisConstant.USER_COMMENT_LIKED_AUX_KEY_PREFIX, userId_liked, cid);

        // 3.执行SADD命令
        Long result = stringRedisTemplate.opsForSet().add(key_postCLiked, userId.toString());
        boolean suc = result != null && result > 0;
        if(suc){
            stringRedisTemplate.opsForZSet().add(key_userCLiked, String.valueOf(cid), System.currentTimeMillis());

            stringRedisTemplate.opsForZSet().add(key_userCLikedAux, String.valueOf(userId), System.currentTimeMillis());
            stringRedisTemplate.opsForZSet().removeRange(key_userCLikedAux, 0, -3); // 每条评论只记录最新的点赞的两个人
        }
        return suc;
    }

    // 用户取消点赞评论
    private boolean cancelLike(Long cid, Integer userId_liked) {
        // 1.获取当前用户id
        Integer userId = BaseContext.getCurrentId();

        // 2.获取key
        String key_postCLiked = RedisConstant.USER_LIKE_POST_COMMENT_KEY_PREFIX + cid; // 某条评论被哪些用户点赞，查询主体：按评论查询
        String key_userCLiked = RedisConstant.USER_COMMENT_LIKED_KEY_PREFIX + userId_liked;
        String key_userCLikedAux = CommonUtils.formatWithStringFormat(RedisConstant.USER_COMMENT_LIKED_AUX_KEY_PREFIX, userId_liked, cid);

        // 3.执行SREM命令
        Long result = stringRedisTemplate.opsForSet().remove(key_postCLiked, userId.toString());
        boolean suc = result != null && result > 0;
        if(suc){
            stringRedisTemplate.opsForZSet().remove(key_userCLiked, String.valueOf(cid));
            stringRedisTemplate.opsForZSet().remove(key_userCLikedAux, String.valueOf(userId));
        }
        return suc;
    }


}
